﻿using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Resources;

namespace BssDs.Client.UI.Controls.ExtendedControl.Tab
{
	/// <summary>
	/// TabMoveCursor.xaml の相互作用ロジック
	/// </summary>
	public class TabMoveCursor : Adorner
	{
		// TODO パスが変わった場合はここも書き換えること。
		private const string CURSOR_RESOURCE_PATH = "/ExtendedControlsLibrary;component/Tab/TabMoveCursor.xaml";

		protected override int VisualChildrenCount
		{
			get
			{
				return CursorCanvas == null ? 0 : 1;
			}
		}

		private TabItem _pointedItem;
		public TabItem PointedItem
		{
			get
			{
				return _pointedItem;
			}
		}

		private bool _pointToHead;
		public bool PointToHead
		{
			get
			{
				return _pointToHead;
			}
		}

		private Canvas _cursorCanvas = null;
		public Canvas CursorCanvas
		{
			get
			{
				return _cursorCanvas;
			}
			set
			{
				_cursorCanvas = value;
				InvalidateVisual();
			}
		}

		public TabMoveCursor(TabControlEx tabControl)
			: base(tabControl)
		{
			Visibility = Visibility.Hidden;

			Uri uri = new Uri(CURSOR_RESOURCE_PATH, UriKind.Relative);
			StreamResourceInfo info = Application.GetResourceStream(uri);
			XamlReader reader = new XamlReader();
			CursorCanvas = reader.LoadAsync(info.Stream) as Canvas;
		}

		public void Hide()
		{
			_pointedItem = null;
			Visibility = Visibility.Hidden;
		}

		// MoveCursorをitemのところに移動させる。
		// MoveCursorの位置は、マウスカーソルがitemの前半を指していた(pointToHead==true)ら前角、
		// 後半を指していたら後角。
		public void MoveTo(TabItem item, bool pointToHead, bool isVisible)
		{
			_pointedItem = item;
			_pointToHead = pointToHead;
			Visibility = (isVisible ? Visibility.Visible : Visibility.Hidden);

			AdornerLayer layer = this.Parent as AdornerLayer;
			layer.Update();
		}

		public void Rotate(double angle)
		{
			_cursorCanvas.RenderTransform = new RotateTransform(angle);
		}

		public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
		{
			Debug.Assert(_cursorCanvas != null);
			if (Visibility != Visibility.Visible)
				return null;

			TabControlEx tabControl = (TabControlEx)AdornedElement;

			Point p = new Point();
			switch (tabControl.TabStripPlacement)
			{
				case Dock.Top:
					p.X = _pointToHead ? 0 : _pointedItem.ActualWidth;
					p.Y = _pointedItem.ActualHeight;
					break;
				case Dock.Left:
					p.X = _pointedItem.ActualWidth;
					p.Y = _pointToHead ? 0 : _pointedItem.ActualHeight;
					break;
				case Dock.Right:
					p.X = 0;
					p.Y = _pointToHead ? 0 : _pointedItem.ActualHeight;
					break;
				case Dock.Bottom:
					p.X = _pointToHead ? 0 : _pointedItem.ActualWidth;
					p.Y = 0;
					break;
			}

			p = _pointedItem.PointToScreen(p);
			p = tabControl.PointFromScreen(p);

			GeneralTransformGroup result = new GeneralTransformGroup();
			result.Children.Add(base.GetDesiredTransform(transform));
			result.Children.Add(new TranslateTransform(p.X, p.Y));
			return result;
		}

		protected override Size ArrangeOverride(Size finalSize)
		{
			if (_cursorCanvas != null)
				_cursorCanvas.Arrange(new Rect()); // なんか入れればいいらしい(Canvasだから?)

			return finalSize;
		}

		protected override Visual GetVisualChild(int index)
		{
			if (_cursorCanvas == null)
				throw new IndexOutOfRangeException("子要素はない");
			if (index != 0)
				throw new IndexOutOfRangeException("子要素は1つのみ");
			return _cursorCanvas;
		}
	}
}